package com.leyou.item.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.type.TypeReference;
import com.leyou.common.dto.PageDTO;
import com.leyou.common.utils.JsonUtils;
import com.leyou.item.entity.*;
import com.leyou.item.mapper.SpuMapper;
import com.leyou.item.service.*;
import com.leyou.pojo.dto.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class SpuServiceImpl extends ServiceImpl<SpuMapper, Spu> implements SpuService {

    @Autowired
    private CategoryService categoryService;
    @Autowired
    private BrandService brandService;
    @Autowired
    private SpuDetailSerivce spuDetailSerivce;
    @Autowired
    private SkuService skuService;
    @Autowired
    private SpecParamService specParamService;

    //分页查询spu
    @Override
    public PageDTO<SpuDTO> findSpuPage(Long brandId, Long categoryId, Long id, Integer page, Integer rows, Boolean saleable) {
        Page<Spu> spuPage = new Page<>(page, rows);
        QueryWrapper<Spu> spuQueryWrapper = new QueryWrapper<>();
        spuQueryWrapper
                .eq(id != null, "id", id)
                .eq(brandId != null, "brand_id", brandId)
                .eq(categoryId != null, "cid3", categoryId)
                .eq(saleable != null, "saleable", saleable);
        Page<Spu> spus = this.page(spuPage, spuQueryWrapper);
        List<SpuDTO> spuDTOS = SpuDTO.convertEntityList(spus.getRecords());

        spuDTOS.forEach(spuDTO -> {
            //设置品牌名
            spuDTO.setBrandName(brandService.getById(spuDTO.getBrandId()).getName());
            //设置分类名
            String names = categoryService.findCategoryByIds(spuDTO.getCategoryIds()).stream().map(CategoryDTO::getName).collect(Collectors.joining("/"));
            spuDTO.setCategoryName(names);
        });

        return new PageDTO<SpuDTO>(spus.getSize(), spus.getTotal(), spuDTOS);
    }

    //新增商品
    @Override
    @Transactional
    public void addGood(SpuDTO spuDTO) {
        Spu spu = spuDTO.toEntity(Spu.class);
//        spu.setSaleable(false);
        //先存spu获取spuid
        if (save(spu)) {
            //再从spuDTO中取出skuDTO并转换为sku保存
            List<Sku> skuList = spuDTO.getSkus().stream().map(skuDTO -> {
                skuDTO.setSpuId(spu.getId());
                return skuDTO.toEntity(Sku.class);
            }).collect(Collectors.toList());

            skuService.saveBatch(skuList);
            //将spuDTO中的detail取出并保存
            SpuDetail spuDetail = spuDTO.getSpuDetail().toEntity(SpuDetail.class);
            spuDetail.setSpuId(spu.getId());
            spuDetailSerivce.save(spuDetail);
        }
    }

    @Override
    @Transactional
    public void updateGoods(SpuDTO spuDTO) {

        Long spuId = spuDTO.getId();

        SpuDetailDTO spuDetail1 = spuDTO.getSpuDetail();

        List<SkuDTO> skuDTOs = spuDTO.getSkus();

        //判断修改逻辑要不要执行
        if (null == spuId && null == spuDetail1 && (null == skuDTOs || 0 == skuDTOs.size())) {
            return;
        }

        //有spuId，说明spu要改
        if (null != spuId) {
            Spu spu = spuDTO.toEntity(Spu.class);
            updateById(spu);
        }

        //如果有spuDetail，说明spuDetail要改
        if (null != spuDetail1) {
            SpuDetail spuDetail = spuDTO.getSpuDetail().toEntity(SpuDetail.class);

            this.spuDetailSerivce.updateById(spuDetail);
        }
        //如果skus数组有值说明sku要改
        if (null != skuDTOs && 0 != skuDTOs.size()) {
            //分组，

            //分组函数，分组的条件为skuDTO得到saleable属性的值，如果属性值为  true,false
            Map<Boolean, List<Sku>> skuMap = skuDTOs
                    .stream()
                    .map(skuDTO -> skuDTO.toEntity(Sku.class))
                    .collect(Collectors.groupingBy(sku -> {
                        return sku.getSaleable() == null;
                    }));

            //true的一组表示的为新增或者修改（新增和修改时不提交saleable所以值为null）
            List<Sku> skus1 = skuMap.get(true);
            if (null!=skus1) this.skuService.saveOrUpdateBatch(skus1);

            //为false的一组表示要删除
            List<Sku> skus2 = skuMap.get(false);
            if (skus2 != null) {//判断是否需要删除
                this.skuService.removeByIds(skus2.stream().map(Sku::getId).collect(Collectors.toList()));
            }
        }
    }
    /**
     * 根据spuId查询spu的所有规格参数值
     *
     * @param id        商品id
     * @param searching 是否支持搜索
     * @return
     */
    @Override
    public List<ParamDTO> findParamBySpuId(Long id, Boolean searching) {
        //查询商品获取商品的分类id再查询分类对应的参数
        List<ParamDTO> params = specParamService.findParamsByIdOrSearching(this.getById(id).getCid3(), null, searching);
        //查询商品对应参数值
        SpuDetail detail = spuDetailSerivce.getById(id);
        //将specification转换为map对象
        Map<Long, Object> detailMap =
                JsonUtils.nativeRead(
                        spuDetailSerivce.getById(id).getSpecification(),
                        new TypeReference<Map<Long, Object>>() {
                        });
        //将detail中的参数值存入params中
        params.forEach(paramDTO -> paramDTO.setValue(detailMap.get(paramDTO.getId())));
        return params;
    }

    //修改商品上下架
    @Override
    @Transactional
    public void updateSaleableById(Long id, Boolean saleable) {
        //修改spu
        UpdateWrapper<Spu> spuUpdateWrapper = new UpdateWrapper<>();
        spuUpdateWrapper.eq("id", id);
        spuUpdateWrapper.set("saleable", saleable);
        this.update(spuUpdateWrapper);
        //修改sku
        UpdateWrapper<Sku> skuUpdateWrapper = new UpdateWrapper<>();
        skuUpdateWrapper.eq("spu_id", id);
        skuUpdateWrapper.set("saleable", saleable);
        skuService.update(skuUpdateWrapper);
    }

    //根据id查询spu及sku、spuDetail等
    @Override
    public SpuDTO queryInfoBySpuId(Long id) {
        //查询spu
        SpuDTO spuDTO = new SpuDTO(getById(id));
        //查询sku
        List<SkuDTO> skuDTOS = SkuDTO.convertEntityList(skuService.list(new QueryWrapper<Sku>().eq("spu_id", id)));
        //查询detail
        SpuDetailDTO spuDetailDTO = new SpuDetailDTO(spuDetailSerivce.getById(id));

        spuDTO.setSkus(skuDTOS);
        spuDTO.setSpuDetail(spuDetailDTO);
        spuDTO.setBrandName(brandService.getById(spuDTO.getBrandId()).getName());
        spuDTO.setCategoryName(categoryService.findCategoryByIds(spuDTO.getCategoryIds()).stream().map(CategoryDTO::getName).collect(Collectors.joining("/")));
        return spuDTO;
    }

    //根据id查询商品
    @Override
    public SpuDTO querySpuById(Long id) {
        return new SpuDTO(this.getById(id));
    }
}
